Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add architecture targeting proposal #233

Merged
merged 10 commits into from
Aug 12, 2021
Merged

Add architecture targeting proposal #233

merged 10 commits into from
Aug 12, 2021

Conversation

richlander
Copy link
Member

This proposal supports x64 emulation on Arm64 operating systems. In particular, it enables targeting x64 runtimes with the Arm64 SDK. It also resolves general architecture targeting challenges with the SDK.

Notably, it includes:

  • Additive changes in .NET 6.
  • Breaking changes in .NET 7.

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@terrajobst
Copy link
Member

FYI, I've changed the author tag so it works with the indexing tools and designsof.net.

Co-authored-by: Marc Paine <marcpop@microsoft.com>
- Use the existing `any` RID to mean portable.
- Expose a new CLI arg and MSBuild property for portable apps, like `--portable` and `<Portable>true</Portable>`.

Recommendation: Start with using just the RID. Wait for feedback to enable more polished experiences to validate that portable is an important scenario.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we need the MSBuild option from day 1 or some alternative.

dotnet build --runtime ... MyRepo.sln fails today with error NETSDK1134: Building a solution with a specific RuntimeIdentifier is not supported. If you would like to publish for a single RID, specifiy the RID at the individual project level instead. and so you cannot actually decide to build an entire solution for a given RID. Doing this per project is slow and unmaintainable for larger projects.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. I didn't know that. I didn't include .sln files in my experiments/research. Fail on that.

I take it that you'd be fine with -r any as long as it is respected on a .sln file. Yes?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I take it that you'd be fine with -r any as long as it is respected on a .sln file. Yes?

Yes, provided you can build the entire solution as desired with a single command, I think that "fits the bill".

However, it's generally nice to be able to do just dotnet build or just dotnet run and have things work as expected and not have to pass command line args for it to be "correct" (assuming the project wants portable by default).


### Use SDK RID as default RID

RID-specific apps should default to the SDK RID as an implicit RID, and no longer require a RID to be specified. The SDK already does this for the apphost for portable apps. This proposal is a straightforward extension of that behavior.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just as an FYI, NuGet has some issues today with RID specific assets: NuGet/Home#10571

Ideally these would get fixed as part of this to ensure that pulling in native dependencies "just works".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup. We need a followon spec that improves building and consuming RID-specific packages. So many problems. @terrajobst has tried to resolve this in the past. I'd like us to take another run at it for .NET 7.


This means that the following commands would produce a RID-specific framework-dependent app:

- `dotnet build -r linux-x64`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How much thought has been put forward on linux-x64? Unlike Windows, there can be a lot of differences between the various distros and writing a portable Linux app can be difficult.

In some cases, you might have different native dependencies for Ubuntu vs RHEL vs SLES vs etc (and sometimes even different dependencies between each of these due to differences in what ships in the system by default).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very little thought. I'd heard very few requests for build-time differentiation. We are forced to do it for Alpine (musl libc), but that's logically separate from what you are getting at. Certainly, we could extend the RID graph for distros. We need compelling scenarios.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One scenario that comes to my mind is dealing with openssl since there can be different incompatible versions/variants between distros and versions of the same distro.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have that problem solved. Put another way, I don't think enable linux as any any-style RID would change our approach to OpenSSL. Same with ICU. Perhaps I'm missing something.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have solved it for the .NET Runtime dependencies on icu and openssl by using non-standard mechanisms to bind to these libraries. The solution was non-trivial to setup and requires constant maintenance. (In theory, we could have used similar non-standard mechanism to bridge the glibc/musl differences too, but that was too complex even for our taste, so we choose to let glibc/musl bleed out in the UX.)

We have not solved it for 3rd party packages with native libraries that depend on openssl, icu and other native libraries. For example, the dependency on libtinfo was giving me a hard time in one of my projects. I think it is rare for authors of 3rd party packages with native dependencies to go through the pains of targeting generic linux RID. The authors of 3rd party packages with native dependencies typically end up picking up a set of Linux distros, configurations and architectures to build and package the native dependencies for. If your project target platform is lucky to be on this list, great! If it is not, you are on a unhappy path.

The only scalable way to solve this is to add fallback to build-from-source for the native dependencies (#233 (comment)). Fallback to build-from-source would work well for current-RID-specific publish, so this proposal is good for it. It would not work well (without additional manual configuration) for RID-neutral publish.

@tannergooding
Copy link
Member

One of the concerns I have is that not everyone has the resources that Microsoft (or "large enterprise") has. Successfully publishing and deploying for every architecture can be a pain and may require additional hardware or resources that are not easily available or commonplace. Not everyone, in fact I'd say most non enterprises, can afford both a Windows/Linux [dual boot] and an Apple machine, let alone an Android + iPhone nor to mention x86 vs x64 vs Arm32 vs Arm64 vs (and not getting into chipset specific optimizations that frameworks like the BCL have, which can greatly impact overall perf). Likewise, when you start looking at native dependencies (particularly on Linux) you can quickly explode into supporting 10+ operating system/architecture combinations.

and so, IMO, it would be nice if we had the option of managing what is portable and what is not at a more granular level and if certain "post processing" (e.g. crossgen and linking/triming) tools were made available for use as "separate" steps/tools. That is, I should be able to create a "portable" windows app that has all my IL. I should then be able to separate that "portable" code from any non-portable bits (crossgen'd or trimmed/linked binaries, native executable hosts, native dependencies, etc). When deploying, I should be able to easily take those bits and produce something that is "xcopyable" (that is, you can put it on a USB drive and move it between two Windows machines and have it still "work"), that is mostly xcopyable minus selected dependencies (e.g. I can make it framework dependent or requiring some native dependency to be pre-installed by the user), or I can package it up in an installer and leave steps like crossgen or trimming/linking to install time. This allows me to optimize the app more and can get even more benefits when you know the exact machine you are targeting. This is fine because installers are there own apps that often setup things like config files or registry keys and are typically not expected to be copyable elsewhere

This would give users the option to target and deploy in the model that works best for them and their scale. If perf isn't a huge concern for my small CLI tool, I can produce something that is framework dependent and where the only non-portable bits are the native hosts that make it easy to launch the tool (that is, xcopyable zips are identical minus the single PE/Elf executable). While if I'm doing a game or an app where optimizations can really make or break things, I can either do the full end to end on my CI machines and produce pre-crossgen'd, linked, and trimmed binaries for each platform or I can ship an installer that gives users the option to spend some extra install time to get faster startup times and that last 15fps.

@jkotas
Copy link
Member

jkotas commented Jul 10, 2021

Likewise, when you start looking at native dependencies (particularly on Linux) you can quickly explode into supporting 10+ operating system/architecture combinations.

Agree. It has been a problem for arm64 and wasm, both of which we want to be growing. I believe that adding source distribution as fallback option for native dependencies is the only scallable way to address this.

I can package it up in an installer and leave steps like crossgen or trimming/linking to install time.

It would an option for CLI tools or desktop app installers only, and it is getting increasingly problematic even for those due to security issues with installers producing unsigned native binaries.

* RID-specific framework-dependent app
* RID-specific self-contained app

Note: The first build type is the default today.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is true (e.g. Client Blazor) and in .NET7 e.g. MAUI

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not true for mobile SDKs (iOS, tvOS, etc), where only the third build type is valid.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally true. My thinking is that these app types already have bespoke build experiences so many of these default experiences don't apply. Fair?


Portable apps are easier to deploy to production for PaaS scenarios, like Azure Websites. As soon as developers adopt containers, it makes more sense to adopt our [documented RID-specific container patterns](https://github.com/dotnet/dotnet-docker/tree/main/samples/aspnetapp), which results in optimized apps.

The reason to keep portable apps as the default is that it is easier for non-container web developers that target a different operating system than the one they use locally for development. Portable apps are significantly worse for all other scenarios, particularly client.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason to keep portable apps as the default is that it is easier for non-container web developers that target a different operating system than the one they use locally for development.

Do we have any evidence that this workflow is used by developers?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't, but I expect it happens a lot. For example, anyone who publishes directly from Visual Studio to a cloud may benefit from this. That said, I'm not arguing this point just conceding that this could be a legit reason.


### Enable RID-specific as default build type

The default build type should be changed to the RID-specific framework-dependent model. This approach has the following benefits:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the intention to change every existing template? In other words will unit test project not produce RID specific framework model?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't a template change. I don't think unit tests care one way or the other. Unless I'm missing something, I'd expect them to be the least impacted.


### Use SDK RID as default RID

RID-specific apps should default to the SDK RID as an implicit RID, and no longer require a RID to be specified. The SDK already does this for the apphost for portable apps. This proposal is a straightforward extension of that behavior.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this going to work on configurations where SDK is built for the more generic RID than I'm on (e.g. some Linux flavours) ?

Copy link
Member

@zivkan zivkan Jul 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

edited: I wanted to post in a new conversation, but clicking the blue + on the same line number, GitHub's forcing me to add a comment to this thread :( I'll repost on a different line.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the most part, we don't offer RIDs for different Linux distros (AFAIK). The key outlier is Alpine. Outside of Alpine, I don't see that mattering. Today, the product only cares about glibc and musl c.

@tannergooding
Copy link
Member

tannergooding commented Jul 12, 2021

It would an option for CLI tools or desktop app installers only, and it is getting increasingly problematic even for those due to security issues with installers producing unsigned native binaries.

@jkotas, I don't disagree here. However, I do feel there is a large difference in expectations and potential acquisition avenues between things like Android/iOS or xbox/playstation and Desktop. The former which provide official "app stores" and sometimes their own recommendations/tools/procedures for optimizing per device and which offset or completely cover the costs of CDN, global distribution, caching, etc.

With standard desktop installs users are often fronting the costs themselves or have some "free/low tier" limitation on bandwidth/CDN to help keep costs low. Even NuGet has a limit (of like 250MB) per package and even compressed, there are apps that can hit that relatively quickly (particularly with native dependencies).

Some of this is improving with things like the Microsoft Store or winget, but its still not perfect and many users still prefer to use things like MSIs or self extracting installers instead and I feel that ensuring the options are available (and maybe even providing guidance and tooling to help make "correct" and "safe" installers that do this viable) might be something worth looking into.

* RID-specific framework-dependent app
* RID-specific self-contained app

Note: The first build type is the default today.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not true for mobile SDKs (iOS, tvOS, etc), where only the third build type is valid.

accepted/2021/architecture-targeting.md Outdated Show resolved Hide resolved
- `dotnet build -r win-x64 --self-contained true`
- `dotnet build -r win-x64 --self-contained false`
- `dotnet build -r win-x64 --no-self-contained`
- Add warning when using `-r` without a `--self-contained` or `--no-self-contained`. The warning is for .NET 6+ apps only.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For platforms that only support self-contained apps (or vice versa if that exists), it seems redundant to have to specify it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does. Someone has to win ;)

More seriously, -r is an equally legit option for framework dependent apps and self-contained ones. IMO, it is incoherent to change the deployment mode as a result of specifying a RID.

This means that the following commands would produce a RID-specific framework-dependent app:

- `dotnet build -r linux-x64`
- `dotnet publish -r linux-x64 /p:PublishReadyToRun=true`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also consider how NuGet lock files should work. Today, the following commands result in an error: NuGet/Home#9195

dotnet new console
dotnet restore --use-lock-file
dotnet restore --locked-mode -r linux-x64

While that looks like a contrived example (why would someone restore locked mode for a specific RID?), consider that customers want to use locked mode on CI build pipelines (via Directory.Build.props or environment variable), and that dotnet publish -r linux-x64 does an implicit restore. Bang, restore failed, so publishing failed, and CI failed.

Customers want to use lock files and locked mode so they can use floating versions, but still get consistent restores across all machines, and also some package substitution prevention, as lock files ensure the package's content hash is the same when packages are extracted.

There needs to be a way for the SDK to ensure that the set of packages NuGet is asked to restore (plus the set of RIDs that NuGet is informed about) is consistent, regardless of what RID is being built/published by the comment line arguments.

This spec seems to be a higher level than these details, but lock files need to be designed to be workable from the top. NuGet can't have a workable lock file experience when the SDK reports a different set of packages on different actions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good issue. I hadn't thought about that. Fortunately, this change doesn't come until .NET 7 so we'll have time properly design this experience. I agree with you.

Co-authored-by: Rolf Bjarne Kvinge <rolf@xamarin.com>
@richlander
Copy link
Member Author

@tannergooding -- the CLI/msbuild offers significant options for application portability today. None of those are being taken away. I'm only moving them to non-default. In fact, making portable non-default may enable us to reason about it better. That said, I think there is a small set of apps where it makes sense. I talked to multiple people on the team that don't understand how portable works, in part, because it is the default.

I see a spectrum of choices:

  1. x64 only and fully optimized (relying on x64 emulation on Arm64).
  2. portable with architecture-specific launchers (which would be a new feature) and not optimized (no R2R).
  3. Same as above but with architecture-specific composite R2R.

The middle option is the sweet spot, IMO. The first one will likely have noticeable perf challenges due to emulation. The last may suffer from size challenges. R2R is only meaningful for large apps and that's where size is likely to show up.

Note: I'm thinking desktop client apps. If it's tools, then we already have a good enough story, IMO. You'll need to convince me otherwise on that front.

This scenario really only applies to Windows. I'm waiting for Arm64 adoption to demonstrate itself before spending any time thinking about this. We're doing our part to support Windows Arm64 and are not holding anyone back (IMO) with the lack of this experience. This scenario is very much a "++" experience that requires more justification before investing.

@AraHaan
Copy link
Member

AraHaan commented Aug 1, 2021

Also with this being a thing could it also be valid to allow AnyCPU self-contained apps where if they do not set an RID then bundle in the x86, x64, and arm64 runtimes into it and have it's loader a select which runtime to use based on:

  • is the cpu x86? (or i386)
  • is the cpu x64?
  • is the cpu arm64?

I would love this so much so that way I do not have to worry then, plus if my application later pulls in some C++ bits then I could consider that part of the runtime and as such separate them like that as well without issues.

Just a thought about this though.

@richlander
Copy link
Member Author

richlander commented Aug 3, 2021

@AraHaan ... I like the idea and it's possible to achieve but it is unclear how. The executables all need to be RID specific. That's a requirement of the operating system. If you've got ideas on how to get around this, can you share the file layout that you'd expect? I can provide more context if that helps.

@AraHaan
Copy link
Member

AraHaan commented Aug 3, 2021

I would figure the layout of the runtime parts would be like so:

  • root of the self contained application
  • runtimes
    • x64
      • runtime dll's here (including user made C++ dll's, this also includes dll's made using C++/CLI).
    • x86
      • runtime dll's here (including user made C++ dll's, this also includes dll's made using C++/CLI).
    • arm64
      • runtime dll's here (including user made C++ dll's, this also includes dll's made using C++/CLI).
  • Application's files (All Managed without any C++ targeting AnyCPU)

However I think the Application Host exe part would he a snag however.

But it could be possible to somehow combine multiple cpu targets into that single binary then have it somehow select the right one by checking the CPU's features using some asm code (if it's arm64, x64, or x86)?

As for loading C++/CLI dll's the dll loader of the runtime could check first in the root of the self contained application, then if not found load from the directory of the chosen runtime used to run it.

As for the above then everything would have to be carefully be tied together to actually work out well.

@richlander
Copy link
Member Author

Yes, the exes are the key thing. This article might help better explain the problem. https://news.ycombinator.com/item?id=24256883

* Portable apps and RID-specific builds [do not place native assets in the same location](https://github.com/dotnet/sdk/issues/11754). That should be configurable and is a [confusing behavior](https://github.com/dotnet/sdk/issues/3903).
* It is possible to make an app portable for one operating system, such as for Windows x86, x64, and Arm64, but that isn't enabled.
* Portable apps -- for the apphost -- don't support the universal binaries feature of Windows or macOS, which reduces their utility, particularly for client apps.
* Some users want to target a specific architecture and/or operating system. The SDK produces a self-contained app by default when you do this. Many users (likely most) do not want that.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many users (likely most) do not want that.

Is this actually true? Do we have evidence on the claim?

Maybe I'm too close to the implementation (and probably not our target customer), but I use self-contained apps much more than targeting a specific RID with a framework-dependent app. I've honestly never actually published an app -r XXX --self-contained false outside of testing the feature.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally agree. I think most people don't (A) realize that this model even exists, (B) don't realize why they would use it, and (C) don't understand the syntax. My take is that RID specific fx-dependent apps are the best default for the product. That's much of the thesis of this proposal.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we can get some data around which deployments are used more often.

I would hope that the more used scenarios would be easier for the user - less settings to pass to the command line / set in the .csproj.

Copy link
Member

@tannergooding tannergooding Aug 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think getting deployments for real world desktop apps is also important.

What you want for a simple command line tool and what you want for a game or a more advanced app might be very different. I'm not sure how well this model fits for Paint.NET for example where, from what I've seen from Rick Brew in the C# Community Discord, it seems to be a bit of a different setup and deployment model.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be very hard to reason about usage patterns/data and I don't think it was lead us to the right decision, in part due to what @tannergooding raises.

The current system doesn't align well with user needs. I don't think most users want portable by default and the focus on -r is not good UX. Instead, users can focus on --self-contained and specialize it with a architecture/OS info as an option. I don't see data pointing us in that direction given how challenging the current UX is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-- For reference, the above is also not be speaking abstractly. I maintain several OSS libraries and tools independently of work and these are the kinds of problems I actively run into already.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd ideally be able to produce small portable deployments that the I can then finish doing things like AOT or R2R on at install time or first launch so that startup is fast

This is separate from the overall conversation, but we don't intend to build those experiences. We're focused on dev-time crossgen and awesome JIT features w/nothing in-between. Today, crossgen has a couple characteristics that we really like:

  • The build produces final optimized artifacts, per OS/arch.
  • Those artifacts can be signed.

The NGEN experience had neither of those characteristics and had a ton of UX problems. We're not going to recreate those challenges.

I honestly can't think of a time when I've wanted a fx-dependent app. So I want to verify that most users do want that behavior.

The thinking behind this change is super simple (as I articulate in the doc):

  • fx dependent is the default build type, since .NET Core 1.0.
  • rid-specific is relevant to fx-dependent apps, using an implicit RID, and this will be the default in .NET 7.
  • specifying an explicit rid shouldn't change the deployment type.

I respect and sympathize with the point you are raising. It's legit. My view is coming from a very different direction, as I've articulated. I am a fan of self-contained. Judging by our container image pulls (10s of millions/month), self-contained is not the primary developer scenario.

I think the new model is generally better. It's not better for all cases but that's typical of change.

Also, for the x64 emulation scenario, rid-specific targeting absolutely benefits from self-contained not being the default.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is separate from the overall conversation, but we don't intend to build those experiences.

I think that's unfortunate and is overlooking the independent developer scenario. In particular certain things like signing simply aren't a consideration for many independent developers. Authenticode certs tend to start at $500-600/yr and that's out of reach for a lot of projects (assuming they aren't in the .NET Foundation or similar). Having the ability to easily perform steps at any stage, including post-install, is general goodness IMO and allows developers to setup their CI flow however works best for them, even if they are signing, etc.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I'd rather us focus on dynamic PGO than a post-install NGEN replacement. BTW: I don't think that NGEN was very popular either, particularly among the audience you are describing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that might have been for other reasons and that dynamic PGO isn't really a viable alternative for handling fast startup, its more about tuning the running application to achieve higher end throughput.

I think its worth considering what would be required to make our core build tools, including crossgen, the linker/trimmer, and others usable either standalone or as part of the SDK. I imagine its not much and that its mostly just packaging them as dotnet tools. This would cover the normal "publish" scenario, running them as post-build or independent CI steps, or even integration into custom build pipelines (which frameworks like Unity have).

- `dotnet build -r linux-x64`
- `dotnet publish -r linux-x64 /p:PublishReadyToRun=true`

Developer would add `--self-contained` or `--self-contained true` to create a self-contained app, like with the following command.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since --self-contained is kind of a lot to type. What do you think about adding a short option -s for this switch?

dotnet publish -r linux-x64 -s

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup. Fan of that (or something like it).

If/when we do that, I'd suggest that we enable an implicit RID by default. That would enable this scenario:

PS C:\Users\rich\app> dotnet publish --self-contained
Microsoft (R) Build Engine version 16.8.3+39993bd9d for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  Restored C:\Users\rich\app\app.csproj (in 61 ms).
C:\Program Files\dotnet\sdk\5.0.103\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.RuntimeIdentifierInference.targets(136,5): error NETSDK1031: It is not supported to build or publish a self-contained application without specifying a RuntimeIdentifier. You must either specify a RuntimeIdentifier or set SelfContained to false. [C:\Users\rich\app\app.csproj]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have the RID default to the host OS's platform and architecture.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed an issue on this. dotnet/sdk#19576

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect! Thanks.

@richlander richlander merged commit 5d33d72 into main Aug 12, 2021
@richlander richlander deleted the architecture-targeting branch August 12, 2021 20:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.